/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.valarnin.plugins.citygen.generator;

import com.valarnin.plugins.citygen.Direction;
import java.util.LinkedList;
import java.util.Random;
import org.bukkit.Chunk;

/**
 *
 * @author valarnin
 */
public class City {
    private LinkedList<CityBlock> cityBlocks;
    
    public boolean isAdjacent(int x, int z) {
        for(CityBlock block : cityBlocks) {
            if(block.isAdjacent(x, z)) {
                return true;
            }
        }
        return false;
    }

    boolean isRequired(int x, int z) {
        for(CityBlock block : cityBlocks) {
            if(block.isRequired(x, z)) {
                return true;
            }
        }
        return false;
    }

    boolean addChunk(Chunk chunk, Random random) {
        for(CityBlock block : cityBlocks) {
            if(block.isRequired(chunk.getX(), chunk.getZ())) {
                return block.addChunk(chunk, random);
            }
        }
        
        int randValue = random.nextInt(100);
        //If our randValue is within range, we want to make our buildings bigger
        
        int xSize = 1, zSize = 1;
        
        int x = chunk.getX(), z = chunk.getZ();
        
        if(randValue >= 90) { // 10% chance of having a block of 2x2-3x3
            xSize = random.nextInt(2) + 2;
            zSize = random.nextInt(2) + 2;
        } else if(randValue >= 60) { // 30% chance of having a block of 1x1 - 3x3
            xSize = random.nextInt(3) + 1;
            zSize = random.nextInt(3) + 1;
        }
        
        Direction dir = getCityAdjacentDirection(x, z);
        
        int leftX, rightX, topZ, bottomZ;
        
        switch(dir) {
            case NORTH:
                leftX = xSize == 3 ? x - 1 : x;
                rightX = leftX + xSize;
                topZ = z - 3;
                bottomZ = z;
                break;
            case SOUTH:
                leftX = xSize == 3 ? x - 1 : x;
                rightX = leftX + xSize;
                topZ = z;
                bottomZ = z + 3;
                break;
            case EAST:
                leftX = x - 3;
                rightX = x;
                topZ = zSize == 3 ? z - 1 : z;
                bottomZ = topZ + zSize;
                break;
            case WEST:
                leftX = x;
                rightX = x + 3;
                topZ = zSize == 3 ? z - 1 : z;
                bottomZ = topZ + zSize;
                break;
            default:
                return false;
        }
        
        for(int tmpX = leftX; tmpX <= rightX; ++tmpX) {
            for(int tmpZ = bottomZ; tmpZ <= topZ; ++tmpZ) {
                //If the square we're checking is required
                if(isRequired(tmpX, tmpZ)) {
                    //If the next square on the Z axis is required, add one to X
                    if(isRequired(tmpX, tmpZ+1)) {
                        leftX++;
                        tmpX++;
                    } else {
                        topZ++;
                        tmpZ++;
                    }
                }
            }
        }
        
        //If we're not including our starting chunk, resize to be just the starting chunk
        //as we know that chunk isn't required by another block at this point
        if(leftX > x || rightX < x) {
            leftX = x;
            rightX = x;
        }
        if(topZ > x || bottomZ < z) {
            topZ = z;
            bottomZ = z;
        }
        
        cityBlocks.add(new CityBlock(leftX, rightX, topZ, bottomZ, dir, chunk, random));
        
        return true;
    }

    public Direction getCityAdjacentDirection(int x, int z) {
        for(CityBlock block : cityBlocks) {
            if(block.isAdjacent(x, z)) {
                return block.getDirectionFromThis(x, z);
            }
        }
        
        return null;
    }
    
    public CityBlock getCityBlock(int x, int z) {
        for(CityBlock block : cityBlocks) {
            if(block.isRequired(x, z)) {
                return block;
            }
        }
        
        return null;
    }
    
    public int getTotalChunks() {
        int chunks = 0;
        for(CityBlock cityBlock : cityBlocks) {
            chunks += cityBlock.getTotalChunks();
        }
        return chunks;
    }

    public double getDistance(int x, int z) {
        double distance = Double.MAX_VALUE;
        for(CityBlock cityBlock : cityBlocks) {
            distance = Math.min(distance, cityBlock.getDistance(x, z));
        }
        return distance;
    }
}
